package com.atguigu.gmall.activity.recevier;

import com.atguigu.gmall.activity.model.SeckillGoods;
import com.atguigu.gmall.activity.model.UserRecode;
import com.atguigu.gmall.activity.service.SeckillGoodsService;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.utils.DateUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.Date;
import java.util.List;

@Slf4j
@Component
@SuppressWarnings("all")
public class ActivityReceiver {
    @Autowired
    private SeckillGoodsService seckillGoodsService;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     *  秒杀预热
     * @param channel
     * @param message
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_TASK,durable = "true"),
            value = @Queue(value = MqConst.QUEUE_TASK_1,durable = "true"),
            key = MqConst.ROUTING_TASK_1
    ))

    public void processSeckillGoodsImport(Channel channel, Message message){
        try {
            log.info("[秒杀服务]监听到秒杀商品入库消息");
            //1.查询数据库中当日参加秒杀商品列表:审核状态:通过,秒杀商品库存大于0
            LambdaQueryWrapper<SeckillGoods> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SeckillGoods::getStatus,"1"); //审核状态
            queryWrapper.eq(SeckillGoods::getStockCount,"0"); //库存计数
            String today = DateUtils.formatDate(new Date());
            queryWrapper.apply("date_format(start_time, '%Y-%m-%d') = '" + today + "'");
            List<SeckillGoods> seckillGoodsList = seckillGoodsService.list(queryWrapper);
            if(!CollectionUtils.isEmpty(seckillGoodsList)){

                //2.导入到分布式缓存中
                String seckillGoodsKey = RedisConst.SECKILL_GOODS;
                //2.1.2创建hash操作对象
                BoundHashOperations<String,String,SeckillGoods> hashOps = redisTemplate.boundHashOps(seckillGoodsKey);
                seckillGoodsList.stream().forEach(seckillGoods -> {
                    if(!hashOps.hasKey(seckillGoods.getSkuId().toString())){
                        //2.2将秒杀商品遍历后存入redis中
                        hashOps.put(seckillGoods.getSkuId().toString(),seckillGoods);
                        //2.2.1将参入秒杀商品存入redis-list数据结构
                        String seckillGoodsStockKey = RedisConst.SECKILL_STOCK_PREFIX + seckillGoods.getSkuId();
                        //2.2.2创建商品库存list操作对象
                        BoundListOperations<String,String> listOps = redisTemplate.boundListOps(seckillGoodsKey);

                        //2.2.3遍历商品数量,存入redis
                        for (Integer i = 0; i < seckillGoods.getStockCount(); i++) {
                            listOps.leftPush(seckillGoods.getSkuId().toString());
                        }
                    }
                });
            }

            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
        }
    }

    /**
     * 监听秒杀队列中用户购买意向,完成核心秒杀业务-获取秒杀资格
     * @param userRecode
     * @param channel
     * @param message
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_SECKILL_USER,durable = "true"),
            value = @Queue(value = MqConst.QUEUE_SECKILL_USER,durable = "true"),
            key = MqConst.ROUTING_SECKILL_USER
    ))

    public void processSeckillRequest(UserRecode userRecode,Channel channel,Message message){
        try {
            if(userRecode != null){
                log.info("[秒杀微服务]监听到秒杀请求:{}",userRecode);
                seckillGoodsService.processSeckillRequest(userRecode);
            }
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
        }
    }

    /**
     * 监听获取的到秒杀资格后,扣减秒杀库存
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_SECKILL_STOCK,durable = "true"),
            value = @Queue(value = MqConst.QUEUE_SECKILL_STOCK,durable = "true"),
            key = MqConst.ROUTING_SECKILL_STOCK
    ))
    public void processDeductStock(Long skuId,Channel channel,Message message){
        try {
            if(skuId != null){
                log.info("[秒杀服务]监听到秒杀库存:{}",skuId);
                seckillGoodsService.getDeductSeckillStock(skuId);
            }
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
        }
    }
}